﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;


public static class TExtensions
{
	/// <summary>
	/// From BReusable
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="item"></param>
	/// <returns></returns>
	public static T ToStringToDebugT<T>(this T item) where T : class
	{
			System.Diagnostics.Debug.WriteLine(item==null?  "null":item.ToString());
		return item;
	}
    /// <summary>
    /// http://adventuresdotnet.blogspot.com/2010/06/better-more-type-safe-alternative-to.html
    /// </summary>
    /// <typeparam name="TItem"></typeparam>
    /// <typeparam name="TDest"></typeparam>
    /// <param name="items"></param>
    /// <returns></returns>
    public static IEnumerable<TDest> CastAll<TItem, TDest>(this IEnumerable<TItem> items)
    {
        var p = Expression.Parameter(typeof(TItem), "i");
        var c = Expression.Convert(p, typeof(TDest));
        var ex = Expression.Lambda<Func<TItem, TDest>>(c, p).Compile();

        foreach (var item in items)
        {
            yield return ex(item);
        }
    }

    /// <summary>
    /// From BReusable
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="items"></param>
    /// <param name="toStringFunc"></param>
    /// <param name="seperator"></param>
    /// <returns></returns>
    public static string ToJoinedString<T>(this IList<T> items, Func<int, T, string> toStringFunc, string seperator)
    {

        var sb = new StringBuilder();
        
        for (int i = 0; i < items.Count(); i++)
        {
            sb.Append((i != 0 ? seperator : String.Empty) + toStringFunc(i,items[i]));
           
        }
        return sb.ToString();
    }

    public static string ToStringFromCharArray(this IEnumerable<char> items)
    {
        return items.ToJoinedString(x => x.ToString(), string.Empty);
    }
    /// <summary>
    /// From BReusable
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="items"></param>
    /// <param name="toStringFunc"></param>
    /// <param name="seperator"></param>
    /// <returns></returns>
    public static string ToJoinedString<T>(this IEnumerable<T> items, Func<T, string> toStringFunc, string seperator)
    {
        var sb = new StringBuilder();
        var first=true;
        foreach (var item in items)
        {

            sb.Append((first == false ? seperator : String.Empty) + toStringFunc(item));
            first = false;
        }
        return sb.ToString();
    }


	/// <summary>
	/// From BReusable
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="list"></param>
	/// <param name="action"></param>
	/// <returns></returns>
	public static void ForEach<T>(this IEnumerable<T> list, Action<T> action)
	{
		foreach (var item in list)
			action(item);
	}

	/// <summary>
	/// Fluent ForEach
	/// From BReusable
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="list"></param>
	/// <param name="action"></param>
	/// <returns></returns>
	/// <remarks>'Then' idea from http://community.bartdesmet.net/blogs/bart/archive/2008/02/26/the-missing-operator-foreach.aspx</remarks>
	public static IEnumerable<T> ForEachThen<T>(this IEnumerable<T> list, Action<T> action)
	{
		foreach (var item in list)
			action(item);
		return list;
	}

	/// <summary>
	/// From BReusable
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="values"></param>
	/// <returns></returns>
	public static List<T> ToDebug<T>(this List<T> values)
	{
		foreach (var item in values)
		{
			item.ToStringToDebug();
		}
		return values;
	}
	public static IDictionary<TKey, TValue> AddOrUpdate<TKey, TValue>(this IDictionary<TKey,TValue> dictionary,
		TKey key, TValue value)
	{
		if (dictionary.ContainsKey(key) == false)
			dictionary.Add(key, value);
		else
			dictionary[key] = value;
			return dictionary;
	}

	/// <summary>
	/// From BReusable
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="list"></param>
	/// <param name="action"></param>
	/// <returns></returns>
	public static IList<T> For<T>(this IList<T> list, Action<int, T> action)
	{
		for (int i = 0; i < list.Count(); i++)
		{
			action(i, list[i]);
		}
		return list;
	}


	public static void InsertOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue value)
	{
		if (dictionary.ContainsKey(key))
			dictionary[key] = value;
		else
			dictionary.Add(key,value);
	}
	//public static void InsertOrUpdate<Tkey, TValue>(this Dictionary<Tkey, TValue> dictionary, KeyValuePair<Tkey, TValue> pair)
	//{
	//    dictionary.InsertOrUpdate(pair.Key, pair.Value);
	//}






}
